/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.admin.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springblade.common.cache.DictCache;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.admin.entity.EstateBuilding;
import org.springblade.modules.admin.entity.EstateElevator;
import org.springblade.modules.admin.entity.EstateElevatorUser;
import org.springblade.modules.admin.service.IEstateElevatorService;
import org.springblade.modules.admin.service.IEstateElevatorUserService;
import org.springblade.modules.admin.vo.*;
import org.springblade.modules.admin.mapper.EstateBuildingMapper;
import org.springblade.modules.admin.service.IEstateBuildingService;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.modules.system.entity.Dept;
import org.springblade.modules.system.service.IDeptService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static org.springblade.modules.admin.service.BuildingService.PROJECT_TYPE_CODE;

/**
 * 物业项目表 服务实现类
 *
 * @author ysq
 * @since 2022-05-27
 */
@Service
public class EstateBuildingServiceImpl extends BaseServiceImpl<EstateBuildingMapper, EstateBuilding> implements IEstateBuildingService {

	@Autowired
	private IDeptService deptService;

	@Autowired
	private IEstateElevatorService estateElevatorService;

	@Autowired
	private IEstateElevatorUserService estateElevatorUserService;

	@Override
	public IPage<EstateBuildingVO> selectEstateBuildingPage(IPage<EstateBuildingVO> page, EstateBuildingVO estateBuilding) {
		estateBuilding.setTenantId(AuthUtil.getTenantId());
		List<EstateBuildingVO> list = baseMapper.selectEstateBuildingPage(page, estateBuilding);
		for (int i = 0; i < list.size(); i++) {
			EstateBuildingVO buildingVO = list.get(i);
			buildingVO.setTypeName(DictCache.getValue(PROJECT_TYPE_CODE, buildingVO.getType()));
			String ancestors = buildingVO.getAncestors();
			if (Func.isNotEmpty(ancestors)) {
				List<Long> ancestorsIds = Func.toLongList(ancestors);
				List<Dept> ancestorsDept = deptService.listByIdsOrderByIds(ancestorsIds);
				buildingVO.setAncestorsDept(ancestorsDept);
			}
		}
		return page.setRecords(list);
	}

	@Override
	public EstateBuildingVO detail(Long id) {
		EstateBuilding estateBuilding = baseMapper.detail(id, AuthUtil.getTenantId());
		if (estateBuilding == null) {
			throw new ServiceException("未找到对应数据");
		}
		EstateBuildingVO buildingVO = new EstateBuildingVO();
		BeanUtils.copyProperties(estateBuilding, buildingVO);
		buildingVO.setTypeName(DictCache.getValue(PROJECT_TYPE_CODE, buildingVO.getType()));
		String ancestors = buildingVO.getAncestors();
		if (Func.isNotEmpty(ancestors)) {
			List<Long> ancestorsIds = Func.toLongList(ancestors);
			List<Dept> ancestorsDept = deptService.listByIds(ancestorsIds);
			buildingVO.setAncestorsDept(ancestorsDept);
		}
		return buildingVO;
	}

	@Override
	public boolean batchStatus(List<Long> ids, Integer status) {
		if (status != 0 && status != 1) {
			throw new ServiceException("非法状态参数!");
		}
		EstateBuilding estateBuilding = new EstateBuilding();
		estateBuilding.setStatus(status);
		return baseMapper.update(estateBuilding, Wrappers.<EstateBuilding>lambdaUpdate().in(EstateBuilding :: getId, ids)) > 0;
	}

	@Override
	public List<Map<String, Object>> selectName() {
		return baseMapper.selectName(AuthUtil.getTenantId());
	}

	@Override
	public List<Map<String, Object>> selectDept() {
		return baseMapper.selectDept(AuthUtil.getTenantId());
	}

	@Override
	public List<EstateBuildingDeptVO> selectDeptByBuildingIds(String buildingIds) {
		List<EstateBuildingDeptVO> list = new ArrayList<>();
		Long[] bids = Func.toLongArray(buildingIds);
		for (Long bid : bids) {
			EstateBuildingDeptVO buildingDeptVO = baseMapper.selectDeptByBuildingId(bid, AuthUtil.getTenantId());
			list.add(buildingDeptVO);
		}
		return list;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean batchDept(List<Long> ids, Long deptId) {
		List<EstateBuilding> updateEntityList = new ArrayList<>();
		List<Long> removeElevators = new ArrayList<>();
		for (Long id : ids) {
			EstateBuildingVO estateBuildingVO = baseMapper.selectEstateBuildingById(id);
			if (Func.isEmpty(estateBuildingVO)) {
				continue;
			}

			/**
			 * 规则：
			 * 1: 还未分配机构,则直接更换机构
			 * 2：若新机构与当前机构相同、或为上级机构及以上机构（都拥有共同的祖父机构），则直接更换机构，且原有的电梯管理人员信息不做变化
			 * 3：若新机构为当前机构的平、下级公司或各自有不同的祖父机构，则清空原有的电梯管理人员信息。
			 */
			EstateBuilding estateBuilding = new EstateBuilding();
			BeanUtils.copyProperties(estateBuildingVO, estateBuilding);
			estateBuilding.setDeptId(deptId);
			updateEntityList.add(estateBuilding);
			boolean isRemovePeople = Func.isEmpty(estateBuildingVO.getDeptId()) || Objects.equals(deptId, estateBuildingVO.getDeptId()) || estateBuildingVO.getAncestors().contains(String.valueOf(deptId));
			if (!isRemovePeople) {
				List<EstateElevator> estateElevators = estateElevatorService.getListByEstateBuildingId(id);
				if (Func.isNotEmpty(estateElevators)) {
					removeElevators.addAll(estateElevators.stream().map(t -> t.getElevatorId()).collect(Collectors.toList()));
				}
			}
		}

		// 清空原有的电梯管理人员信息
		if (removeElevators.size() > 0) {
			estateElevatorUserService.removeElevatorUser(removeElevators);
		}

		return this.updateBatchById(updateEntityList);
	}

	@Override
	public boolean checkDept(List<Long> ids, Long deptId) {
		for (Long id : ids) {
			EstateBuildingVO estateBuildingVO = baseMapper.selectEstateBuildingById(id);
			if (Func.isEmpty(estateBuildingVO)) {
				continue;
			}
			boolean isRemovePeople = Func.isEmpty(estateBuildingVO.getDeptId()) || Objects.equals(deptId, estateBuildingVO.getDeptId()) || estateBuildingVO.getAncestors().contains(String.valueOf(deptId));
			if (!isRemovePeople) {
				List<EstateElevator> estateElevators = estateElevatorService.getListByEstateBuildingId(estateBuildingVO.getId());
				if (Func.isNotEmpty(estateElevators)) {
					List<Long> elevatorIds = estateElevators.stream().map(t -> t.getElevatorId()).collect(Collectors.toList());
					int elevatorUserCount = estateElevatorUserService.count(Wrappers.<EstateElevatorUser>lambdaQuery().in(EstateElevatorUser :: getElevatorId, elevatorIds));
					if (elevatorUserCount > 0) {
						return true;
					}
				}
			}
		}
		return false;
	}

	@Override
	public Integer estateCompanyCountStatistics() {
		Integer estateCompanyCount = baseMapper.estateCompanyCountStatistics();
		return estateCompanyCount;
	}

	@Override
	public List<MaintainPlanContentVO> estateMalElevatorPlanList(String tenantId, Date startTime, Date endTime) {
		return baseMapper.estateMalElevatorPlanList(Func.isEmpty(tenantId) ? AuthUtil.getTenantId() : tenantId, startTime, endTime);
	}

	@Override
	public List<EstateElevatorVO> estateElevatorList(String tenantId) {
		return baseMapper.estateElevatorList(Func.isEmpty(tenantId) ? AuthUtil.getTenantId() : tenantId);
	}
}
